package io.github.tangwan.utils;


import net.sf.cglib.beans.BeanCopier;
import io.github.tangwan.exceptions.CopyBeanException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * cglib使用动态代理,BeanUtils使用反射机制,cglib速度更快
 * @author tangwan
 * @date 2018/4/14 23:07
 * @since JDK 1.8
 * @version V1.0
 */
public abstract class CglibCopyBeanUtil {

	/**
	 * 对象间名称相同可以copy属性值,不相同的属性为null
	 * @param source 有值得部分
	 * @param target 目标对象
	 */
	public static void basicCopyBean(Object source, Object target) {
		if (null != source) {
			BeanCopier copier = BeanCopier.create(source.getClass(), target.getClass(), false);
			copier.copy(source, target, null);
		}
	}

	/**
	 * 对象间名称相同可以copy属性值,不相同的属性为null
	 * @param source 有值对象
	 * @param c 目标类字节码对象
	 * @param <T> 目标对象类型
	 * @return T
	 */
	@SuppressWarnings("unchecked")
	public static <T> T doClone(Object source, Class<T> c){
		if (source == null) {
			return null;
		}
		Object target;
		try{
			target = c.newInstance();
			BeanCopier copier = BeanCopier.create(source.getClass(), c, false);
			copier.copy(source, target, null);
		}catch (Exception e){
			throw new CopyBeanException("copyBean异常",e);
		}
		return (T) target;
	}
	
	/**
	 * 批量复制bean,copy一个list对象
	 * @param src 源对象
	 * @param c 目标对象Class
	 * @param <T> 目标对象类型
	 * @return List<T>
	 */
	@SuppressWarnings("TypeParameterExplicitlyExtendsObject")
    public static <T> List<T> doBatchClone(List<? extends Object> src, Class<T> c){
		if (src == null || src.size() ==0) {
			return null;
		}
		List<T> list = new ArrayList<>(src.size());
		for (Object obj : src) {
			T doClone = doClone(obj, c);
			list.add(doClone);
		}
		return list;
	}

	/**
	 * copy map到指定类型对象
	 * @param map 源map
	 * @param clazz	目标对象Class
	 * @param <T>	目标对象类型
	 * @return T
	 */
	public static <T> T copyMap(Map<String,Object> map, Class<T> clazz){
		T obj;
		try {
			obj = clazz.newInstance();
			for (String key : map.keySet()) {
				if(map.get(key) != null) {
					try {
						Method method = clazz.getMethod("set" + key.replaceFirst(String.valueOf(key.charAt(0)), String.valueOf(key.charAt(0)).toUpperCase()), map.get(key).getClass());
						method.invoke(obj, map.get(key));
					}catch(Exception e){
						try {
							Method method = clazz.getMethod("set" + key.replaceFirst(String.valueOf(key.charAt(0)), String.valueOf(key.charAt(0)).toUpperCase()), map.get(key).getClass().getSuperclass());
							method.invoke(obj, map.get(key));
						}catch (Exception ex) {
							throw new CopyBeanException("不能映射基础类型数据",ex);
						}
					}
				}
			}
		}catch(Exception e){
			throw new CopyBeanException("copyBean异常",e);
		}
		return obj;
	}

	/**
	 * 批量copy map到指定Class对象
	 * @param maps 源map list
	 * @param clazz 目标Class对象
	 * @param <T>	目标类型
	 * @return List<T>
	 */
	public static <T> List<T>  copyMapList(List<Map<String, Object>> maps, Class<T> clazz) {
		ArrayList<T> list = new ArrayList<>();
		for (Map<String, Object> map : maps) {
			T obj = copyMap(map, clazz);
			list.add(obj);
		}
		return list;
	}

}
